/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef PRIMITIVE_H
#define PRIMITIVE_H

/* 
 * definition file for CPrimitive
 *
 * CPrimitive is base class for primitive geometric parts like boxes, spheres...
 * This mostly wraps ode-primitives to more (imo) user friendly package.
 * This also provides a drawing function for primitives.
 * Primitive has a material that defines its physical and visual properties.
 * Primitive can be static, which means it has only geom attached to worlds'
 * static environment. If primitive is static its state is not afflicted by 
 * simulation, but it still works as an obstacle in collisions (useful when 
 * creating walls).
 * To use primitive in simulations, use it inside objects.
 * 
 * TODO: 
    -possibility to generate displaylists for primitive graphics
    -composite objects
 */

#include <cstdlib>

#include "ode/ode.h"
#include "Material.h"

struct TMaterial;
class CObject;
class CPrimitive;

struct TGeomData
{
  TGeomData()
  :Primitive(NULL),
  userData(NULL)
  {}
  
  CPrimitive *Primitive;
  void *userData;
};

class CPrimitive
{
  public:
    CObject *ParentObject; // the object that this primitive belongs to (this is needed after all :P)
    dWorldID WorldID;
    dSpaceID SpaceID; //the space that primitive belongs to
    
    //is primitive static
    const bool IsStatic; 
    
    //are collisions reported
    bool NotifyCollisions;
    
    //pointer to material this geom has
    const TMaterial *Material;
    
    dBodyID BodyID;
    dGeomID GeomID; //geom transform, use this as normal geom
    dGeomID _GeomID; //encapsulated geom 
    dMass Mass; //objects mass
    
    TGeomData *GeomData;
    
    /*constructor*/
    CPrimitive(CObject *ParentObject, dSpaceID SpaceID, dBodyID parentBodyID=0,
              const TMaterial *Material=&DEFAULT_MATERIAL, bool IsStatic=false);
    
              
    virtual ~CPrimitive();
    /*
    * Draws this primitive
    * Must be defined by subclasses
    */
    virtual void Draw()=0;
    
    /* 
    * Gives primitives position and rotation in a homogenous 4x4 transformation-
    * matrix. Useful when drawing, as matrix can be given directly to OGL.
    */       
    void GetBodyTransMatrix(dReal *M); 
    
    void GetGeomTransMatrix(dReal *M); 
    
    /*
    * This is called when primitive's geom has a collision. Contacts created in
    * collision and other Primitive (NULL if none) are passed as parameter. Primitive further informs its parent 
    * object of collision.
    */
    void OnCollision(int numc, dContact *contacts, CPrimitive *primitive);

  private:
    /*
    * force subclasses to use aforementioned constructor to ensure proper 
    * initialization 
    */
    CPrimitive()
    :IsStatic(false)
    {}
    
    //if body has been created in constructor
    bool createdBody;
};

#endif //PRIMITIVE_H
